//
// Created by miaomiaole on 2024/1/22.
//

#include "src_imgs_gray.h"


int main() {
/*

    Mat dst;
    auto source = imread("./picture_1663037518439.jpeg");
    // 灰图
    auto gray = imread("./picture_1663037518439.jpeg", IMREAD_GRAYSCALE);
    imshow("input", source);

    imshow("gray", gray);

    // 创建单通道灰图
    dst.create(source.rows, source.cols, CV_8UC1);


    gray_exp_imgs(source, dst);


    imshow("dst", dst);

    auto line_images = linearTransform(source);

    imshow("line_images", line_images);


    auto source_png = imread("./img.png");

    namedWindow("source_png", WINDOW_NORMAL);
    imshow("source_png", source_png);


    auto gray_peng = imread("./img.png", IMREAD_GRAYSCALE);

    namedWindow("gray_peng", WINDOW_NORMAL);

    auto linearStrength = dividedLinerStreangth(gray_peng);
    namedWindow("linearStrength", WINDOW_NORMAL);
    imshow("linearStrength", linearStrength);

    namedWindow("IMG_20161003_182919.jpg", WINDOW_NORMAL);

    namedWindow("IMG_20161003_182919.jpg", WINDOW_NORMAL);

    auto imgs = imread("./IMG_20161003_182919.jpg", IMREAD_GRAYSCALE);


    imshow("IMG_20161003_182919.jpg", dividedLinerStreangth(imgs));
*/

    auto home = imread("./IMG_20161003_182919.jpg", 0);

    /*  auto linestream = linerStream(home);

      namedWindow("home", WINDOW_NORMAL);
      namedWindow("linestream", WINDOW_NORMAL);

      imshow("home", home);
      imshow("linestream", linestream);
      imwrite("img_20161003.png", linestream);*/

    /* namedWindow("home", WINDOW_NORMAL);
     imshow("home", home);
     auto result = log_transform(home, 1.2);


     namedWindow("result", WINDOW_NORMAL);

     imshow("result", result);*/


/*
    imshow("source", home);

    auto negative = NegativeLogTransform(home, 3);
    namedWindow("negative", WINDOW_NORMAL);
    imshow("negative", negative);*/

    conver_image();


    waitKey(0);

}


void gray_exp_imgs(Mat &input, Mat &output) {
    for (int i = 0; i < input.rows; ++i) {
        for (int j = 0; j < input.cols; ++j) {
            auto R = input.at<Vec3b>(i, j)[0] * 0.114;
            auto G = input.at<Vec3b>(i, j)[1] * 0.587;
            auto B = input.at<Vec3b>(i, j)[2] * 0.2989;
            output.at<uchar>(i, j) = saturate_cast<uchar>(R + G + B);
        }
    }
}

Mat linearTransform(Mat srcImage, float a, int b) {
    const int nRows = srcImage.rows;
    const int nCols = srcImage.cols;
    Mat result = Mat::zeros(srcImage.size(), srcImage.type());

    for (int i = 0; i < nRows; ++i) {
        for (int j = 0; j < nCols; ++j) {
            result.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(a * (srcImage.at<Vec3b>(i, j)[0]) + b);
            result.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(a * (srcImage.at<Vec3b>(i, j)[1]) + b);
            result.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(a * (srcImage.at<Vec3b>(i, j)[2]) + b);
        }
    }
    return result;
}


Mat dividedLinerStreangth(Mat &matInput, float fStart, float fEnd, float fSout,
                          float fEout) {
    float fK1 = fSout / fStart;
    float fK2 = (fEout - fSout) / (fEnd - fStart);
    float fC2 = fSout - fK2 * fStart;
    float fK3 = (255.0f - fEout) / (255.0f - fEnd);
    float fC3 = 255.0f - fK3 * 255.0f;
    vector<unsigned char> loolUpTable(256);

    for (size_t m = 0; m < 256; m++) {
        if (m < fStart) {
            loolUpTable[m] = static_cast<unsigned char>(m * fK1);
        } else if (m > fEnd) {
            loolUpTable[m] = static_cast<unsigned char>(m * fK3 + fC3);
        } else {
            loolUpTable[m] = static_cast<unsigned char>(m * fK2 + fC2);
        }
    }

    auto matOutput = static_cast<Mat>(cv::Mat::zeros(matInput.rows, matInput.cols, matInput.type()));

    for (size_t r = 0; r < matInput.rows; r++) {
        unsigned char *pInput = matInput.data + r * matInput.step[0];
        unsigned char *pOutput = matOutput.data + r * matOutput.step[0];
        for (size_t c = 0; c < matInput.cols; c++) {
            pOutput[c] = loolUpTable[pInput[c]];
        }
    }
    return matInput;

}

/**
 * 分段线性转换概述图片
 * @param input
 * @param alpha
 * @param beta
 * @return
 */
Mat linerStream(Mat &srcImage, float alpha, float beta) {

    auto dstImage = srcImage.clone();

    for (int r = 0; r < srcImage.rows; r++) {
        for (int c = 0; c < srcImage.cols; c++) {
            uchar temp = srcImage.at<uchar>(r, c);
            if (temp < 50) {
                dstImage.at<uchar>(r, c) = saturate_cast<uchar>(temp * 0.5);
            } else if (50 <= temp && temp < 150) {
                dstImage.at<uchar>(r, c) = saturate_cast<uchar>(temp * 3.6 - 310);
            } else {
                dstImage.at<uchar>(r, c) = saturate_cast<uchar>(temp * 0.238 + 194);
            }
        }
    }

    return dstImage;
}

// 对数转换
Mat log_transform(Mat srcImage, int c) {
    auto result = (Mat) Mat::zeros(srcImage.size(), srcImage.type());

    add(srcImage, cv::Scalar(1.0), srcImage);
    // 转换为32位浮点数
    srcImage.convertTo(srcImage, CV_32F);

    log(srcImage, result);

    result = c * result;

    normalize(result, result, 0, 255, NORM_MINMAX);

    convertScaleAbs(result, result);

    return result;

}

Mat Normalize(vector<double> data, int grayscale, int rows, int cols, int type) {
    double max = 0.0;
    double min = 0.0;
    for (int i = 0; i < data.size(); i++) {
        if (data[i] > max)
            max = data[i];
        if (data[i] < min)
            min = data[i];
    }
    Mat dst;
    dst.create(rows, cols, type);
    int index = 0;
    for (int r = 0; r < dst.rows; r++) {
        uchar *dstRowData = dst.ptr<uchar>(r);
        for (int c = 0; c < dst.cols; c++) {
            dstRowData[c] = (uchar) (grayscale * ((data[index++] - min) * 1.0 / (max - min)));
        }
    }
    return dst;
}

Mat NegativeLogTransform(Mat src, double parameter) {
    vector<double> value;
    for (int r = 0; r < src.rows; r++) {
        uchar *srcRowData = src.ptr<uchar>(r);
        for (int c = 0; c < src.cols; c++) {
            //反对数变换公式为s = ((v + 1) ^ r - 1) / v
            value.push_back((pow(parameter + 1, srcRowData[c]) - 1) / parameter);
        }
    }
    //计算得出的s经过对比拉升（将像素值归一化到0-255）得到最终的图像
    return Normalize(value, 255, src.rows, src.cols, src.type());
}


void conver_image() {
    auto home = imread("./IMG_20161003_182919.jpg");
    namedWindow("home", 0);
    imshow("home", home); // 显示输入的图像src;
    cvtColor(home, home, COLOR_RGB2GRAY);

    Mat grayimg;
    grayimg.create(home.size(), home.type());

    int height = home.rows;
    int width = home.cols;
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++) {
            int gray = home.at<uchar>(i, j);
            grayimg.at<uchar>(i, j) = pow(gray, 0.5);//将灰度值开方；
        }
    normalize(grayimg, grayimg, 0, 255, NORM_MINMAX);//归一化，将数据归一到0-255之间；

    namedWindow("output", 0);
    imshow("output", grayimg);

}


